/**
 * 版权所有(C)，上海海鼎信息工程股份有限公司，2009，所有权利保留。
 * 
 * 项目名：	rumba-web
 * 文件名：	RHotItem.java
 * 模块说明：	
 * 修改历史：
 * Sep 14, 2009 - lxm - 创建。
 */
package com.hd123.rumba.gwt.widget2.client.menu;

import com.google.gwt.dom.client.Element;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HasHTML;
import com.google.gwt.user.client.ui.Widget;
import com.hd123.rumba.gwt.widget2.client.misc.RImageLocation;

/**
 * 提供一个界面控件，可以用来修饰任意界面控件，并且指定一个弹出式菜单。当鼠标悬停与该控件上时，将出现一个外框，以及一个向下按钮，
 * 点击该按钮后将显示出弹出式菜单。以此实现页面上的类似上下文菜单的功能。
 * <p>
 * 
 * <b>控件元素结构</b><br>
 * div<br>
 * ..div class=content<br>
 * ..div class=menuButton<br>
 * <p>
 * 
 * <b>CSS Style Rules:</b>
 * <ol type=disc>
 * <li>.rb-HotItem {}</li>
 * <li>.rb-HotItem-hovering { 鼠标悬停状态。 }</li>
 * <li>.rb-HotItem .content { 用于存放被修改部件的&lt;td&gt; }</li>
 * <li>.rb-HotItem .menuButton { 菜单按钮&lt;td&gt; }</li>
 * </ol>
 * 
 * @author lxm
 * 
 */
public class RHotItem extends Composite implements HasHTML {

  private static final String STYLENAME_DEFAULT = "rb-HotItem";

  private static RHotItem hoveringInstance = null;

  /**
   * 创建对象实例。
   */
  public RHotItem() {
    super();
    drawSelf();
  }

  /**
   * 创建对象实例。
   * 
   * @param html
   *            指定所包含的html。
   */
  public RHotItem(String html) {
    this();
    setHTML(html);
  }

  /**
   * 创建对象实例。
   * 
   * @param widget
   *            指定所包含的界面部件。
   */
  public RHotItem(Widget widget) {
    this();
    setWidget(widget);
  }

  /**
   * 创建对象实例。
   * 
   * @param html
   *            指定所包含的html。
   * @param menu
   *            指定弹出式菜单。
   */
  public RHotItem(String html, RPopupMenu menu) {
    this();
    setHTML(html);
    setMenu(menu);
  }

  /**
   * 创建对象实例。
   * 
   * @param widget
   *            指定所包含的界面部件。
   * @param menu
   *            指定弹出式菜单。
   */
  public RHotItem(Widget widget, RPopupMenu menu) {
    this();
    setWidget(widget);
    setMenu(menu);
  }

  private Widget widget;
  private RPopupMenu menu;
  private HandlerRegistration menuHandler;
  private boolean hovering = false;
  private Grid grid;

  private static final RImageLocation menuButtonImage = new RImageLocation(
      "images/menu/menuButton.gif");

  /** 所包含的界面部件 */
  public Widget getWidget() {
    return widget;
  }

  public void setWidget(Widget widget) {
    this.widget = widget;
    grid.setWidget(0, 0, this.widget);
  }

  public String getHTML() {
    return grid.getHTML(0, 0);
  }

  public void setHTML(String html) {
    grid.setHTML(0, 0, html);
  }

  public String getText() {
    return grid.getText(0, 0);
  }

  public void setText(String text) {
    grid.setText(0, 0, text);
  }

  /** 对应的弹出式菜单 */
  public RPopupMenu getMenu() {
    return menu;
  }

  public void setMenu(RPopupMenu menu) {
    if (this.menu != null)
      menuHandler.removeHandler();
    this.menu = menu;
    if (this.menu != null)
      menuHandler = menu.addCloseHandler(new Handler_menu());
  }

  /** 当前是否处于鼠标悬停状态。 */
  public boolean isHovering() {
    return hovering;
  }

  void setHovering(boolean hovering) {
    this.hovering = hovering;
    if (hovering) {
      addStyleDependentName("hovering");
      grid.getCellFormatter().setVisible(0, 1, true);
      hoveringInstance = this;
    } else {
      removeStyleDependentName("hovering");
      grid.getCellFormatter().setVisible(0, 1, false);
      if (hoveringInstance == this)
        hoveringInstance = null;
    }
  }

  public void onBrowserEvent(Event event) {
    super.onBrowserEvent(event);

    switch (DOM.eventGetType(event)) {
    case Event.ONCLICK: {
      Element e = DOM.eventGetTarget(event);
      if (widget == null || e != widget.getElement()) {
        setHovering(true);
        menu.show(this, this, RPopupMenu.bottomRight);
      }
      break;
    }

    case Event.ONMOUSEOVER: {
      if (menu != null && hoveringInstance == null)
        setHovering(true);
      break;
    }

    case Event.ONMOUSEOUT: {
      if (menu != null) {
        if (menu.isShowing() == false)
          setHovering(false);
      }
      break;
    }
    }
  }

  private void drawSelf() {
    grid = new Grid(1, 2);
    grid.setCellPadding(0);
    grid.setCellSpacing(0);
    
    grid.getCellFormatter().setWidth(0, 0, "100%");
    grid.getCellFormatter().setStyleName(0, 0, "content");
    
    grid.setWidget(0, 1, menuButtonImage.createImage());
    grid.getCellFormatter().setStyleName(0, 1, "menuButton");
    grid.getCellFormatter().setVisible(0, 1, false);

    initWidget(grid);
    setStyleName(STYLENAME_DEFAULT);
    sinkEvents(Event.ONCLICK | Event.ONMOUSEOVER | Event.ONMOUSEOUT);
  }

  private class Handler_menu implements CloseHandler {

    public void onClose(CloseEvent event) {
      setHovering(false);
    }

  }

}
